package com.hnx.admin.aurora.aspects;

import com.hnx.admin.aurora.annotation.LoginLog;
import com.hnx.admin.aurora.annotation.LoginValidator;
import com.hnx.admin.aurora.api.cache.CacheAPI;
import com.hnx.admin.aurora.redis.RedisCache;
import com.hnx.admin.aurora.security.api.LoginLogWriter;
import com.hnx.admin.aurora.security.core.SecurityProperties;
import com.hnx.admin.aurora.utils.ReflectUtil;
import com.hnx.admin.aurora.utils.ServletUtil;
import com.hnx.admin.aurora.web.exception.user.UserPasswordLimitException;
import com.hnx.admin.aurora.web.json.ResultJson;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/*
创建人： 倔强的头发
创建时间：2025/6/15
功能描述:

*/
@Aspect
@Component
@RequiredArgsConstructor
public class LoginAspect implements CacheAPI {
    private final RedisCache redisCache;
    private final SecurityProperties securityProperties;
//    private final LoginBeforeValidator loginBeforeValidator;
    private final LoginLogWriter loginLogWriter;

    @Before("@annotation(loginValidator)")
    public void toBefore(JoinPoint jp, LoginValidator loginValidator) {
        HttpServletRequest request = ServletUtil.getRequest();
        if (Objects.nonNull(request)) {
            Object args = jp.getArgs()[ZERO];
            if (Objects.nonNull(request) && Objects.nonNull(args)) {
//                loginBeforeValidator.match(args, request);
                String username = ReflectUtil.getFieldValue(args, "username").toString();
                Integer retryCount = redisCache.getCacheObject(getErrCntKey(username), Integer.class);
                if (retryCount == null) {
                    retryCount = ZERO;
                }
                if (retryCount >= securityProperties.getMaxRetryCount()) {
                    throw new UserPasswordLimitException(securityProperties.getMaxRetryCount(), securityProperties.getLockTime());
                }
            }
        }
    }
    @AfterThrowing(value = "@annotation(loginLog)",throwing = "ex")
    public void toAfterThrow(JoinPoint jp, LoginLog loginLog, Exception ex){
        Object arg = jp.getArgs()[ZERO];
        String username = ReflectUtil.getFieldValue(arg, "username").toString();
        if(ex instanceof BadCredentialsException){
            Integer retryCount = redisCache.getCacheObject(getErrCntKey(username), Integer.class);
            if (retryCount == null)
            {
                retryCount = ZERO;
            }
            retryCount = retryCount + 1;
            redisCache.setCacheObject(getErrCntKey(username), retryCount, securityProperties.getLockTime(), TimeUnit.MINUTES);
        }
        loginLogWriter.writeLog(username,1,ex.getMessage());
    }
    @AfterReturning(value = "@annotation(loginLog)",returning = "json")
    public void toAfter(JoinPoint jp, LoginLog loginLog, ResultJson json){
        Object arg = jp.getArgs()[ZERO];
        String username = ReflectUtil.getFieldValue(arg, "username").toString();
        clearLoginRecordCache(username);
        loginLogWriter.writeLog(username,ZERO,json.get("msg").toString());
    }
    private void clearLoginRecordCache(String loginName)
    {
        if (redisCache.hasKey(getErrCntKey(loginName)))
        {
            redisCache.deleteObject(getErrCntKey(loginName));
        }
    }
}
